package airacrobats.gui.container;

import airacrobats.game.Stage;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.List;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * This is the main menu panel.
 */
public class MainMenuContainer extends JPanel implements ListSelectionListener
{
    /**
     * Play button.
     */
    private JButton playButton;
    /**
     * About button.
     */
    private JButton aboutButton;
    /**
     * Exit button.
     */
    private JButton exitButton;
    /**
     * Stage list.
     */
    private JList stageList;
    /**
     * List model of the stage list.
     */
    private DefaultListModel stageListModel;
    /**
     * Selected stage image.
     */
    private JLabel stageImage;
    /**
     * Stages opened label.
     */
    private JLabel stagesOpenedLabel;
    /**
     * Selected stage description.
     */
    private JTextArea stageDescriptionTextArea;
    /**
     * Panel containing extra information about the game/stage.
     */
    private JPanel infoPanel;
    /**
     * Stages.
     */
    private List<Stage> stages;

    /**
     * @param actionListener Listener notified when the buttons are pressed.
     * @param stages The stages. Note that stages MUST NOT be empty.
     */
    public MainMenuContainer(ActionListener actionListener, List<Stage> stages)
    {
        this.stages = stages;
        
        setLayout(new GridBagLayout());
        setBorder(new TitledBorder("Menu"));

        playButton = new JButton("Play");
        playButton.addActionListener(actionListener);

        aboutButton = new JButton("About");
        aboutButton.addActionListener(actionListener);

        exitButton = new JButton("Exit");
        exitButton.addActionListener(actionListener);

        stageListModel = new DefaultListModel();

        stageList = new JList(stageListModel);
        stageList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        Iterator<Stage> it = stages.iterator();
        while (it.hasNext())
        {
            Stage stage = it.next();
            stageListModel.addElement(stage.getStageData().getName());
            if (stage.getScoreRecord() < stage.getStageData().getNeededScore())
                break;
        }
        stageList.setSelectedIndex(0);
        stageList.addListSelectionListener((ListSelectionListener) this);
        JScrollPane stageListScrollPane = new JScrollPane(stageList);

        stageImage = new JLabel(new ImageIcon(stages.get(0).getImage()));

        stagesOpenedLabel = new JLabel();

        stageDescriptionTextArea = new JTextArea(stages.get(0).getStageData().getDescription(), 7, 40);
        stageDescriptionTextArea.setLineWrap(true);
        stageDescriptionTextArea.setWrapStyleWord(true);
        stageDescriptionTextArea.setBorder(new EmptyBorder(2, 4, 2, 4));
        stageDescriptionTextArea.setEditable(false);
        JScrollPane stageDescriptionScrollPane = new JScrollPane(stageDescriptionTextArea);

        infoPanel = new JPanel(new GridBagLayout());
        
        JPanel buttonsPanel = new JPanel(new GridLayout(3, 1, 0, 5));
        buttonsPanel.add(playButton);
        buttonsPanel.add(aboutButton);
        buttonsPanel.add(exitButton);

        GridBagConstraints c = new GridBagConstraints();

        c.gridx = 0;
        c.gridy = 0;
        c.anchor = GridBagConstraints.NORTH;
        add(buttonsPanel, c);

        c.gridx++;
        c.insets = new Insets(2, 2, 2, 2);
        c.anchor = GridBagConstraints.CENTER;
        c.fill = GridBagConstraints.BOTH;
        add(stageListScrollPane, c);

        c.gridy++;
        c.gridheight = 1;
        add(stageDescriptionScrollPane, c);
        
        c.gridx++;
        c.gridy = 0;
        c.gridheight = 2;
        add(stageImage, c);
    
        c.gridy = 2;
        c.gridx = 0;
        c.gridheight = 1;
        c.gridwidth = 3;
        add(infoPanel, c);

        updateInfoPanel();
    }

    /**
     */
    public void valueChanged(ListSelectionEvent e)
    {
        if (!e.getValueIsAdjusting() && e.getSource() == stageList)
        {
            stageImage.setIcon(new ImageIcon(stages.get(stageList.getSelectedIndex()).getImage()));
            stageDescriptionTextArea.setText(stages.get(stageList.getSelectedIndex()).
                    getStageData().getDescription());
            updateInfoPanel();
            validate();
            repaint();
        }
    }

    /**
     * Disables the panel, setting it to the gaming mode.
     */
    public void startGaming()
    {
        playButton.setEnabled(false);
        playButton.setText("Loading..");
    }

    /**
     * Enable the panel, removing it from the gaming mode and unblocking possible stages.
     */
    public void resetGaming()
    {
        Stage stage = getSelectedStage();
        if (stage.getScoreRecord() >= stage.getStageData().getNeededScore() &&
                stageList.getSelectedIndex() + 1 == stageListModel.size() &&
                stageList.getSelectedIndex() + 1 < stages.size())
        {
            Stage nextStage = stages.get(stageList.getSelectedIndex() + 1);
            if (!stageListModel.contains(nextStage.getStageData().getName()))
                stageListModel.addElement(nextStage.getStageData().getName());
        }

        playButton.setEnabled(true);
        playButton.setText("Play");
        updateInfoPanel();
        validate();
        repaint();
    }

    /**
     * @return The selected stage.
     */
    public Stage getSelectedStage()
    {
        return stages.get(stageList.getSelectedIndex());
    }

    /**
     * Updates the info panel component.
     */
    private void updateInfoPanel()
    {
        infoPanel.removeAll();

        Stage stage = stages.get(stageList.getSelectedIndex());

        GridBagConstraints c = new GridBagConstraints();

        c.gridx = 0;
        c.gridy = 0;
        c.weightx = 1.0;
        c.anchor = GridBagConstraints.WEST;
        stagesOpenedLabel.setText("Stages available: " + stageListModel.size() + "/" + stages.size());
        infoPanel.add(stagesOpenedLabel, c);
        
        c.gridx++;
        c.weightx = 0.0;
        c.anchor = GridBagConstraints.EAST;
        c.insets = new Insets(0, 0, 0, 2);
        infoPanel.add(new JLabel("Needed score:"), c);

        c.gridx++;
        c.weightx = 0.0;
        c.insets = new Insets(0, 0, 0, 30);
        infoPanel.add(new JLabel(Integer.toString(stage.getStageData().getNeededScore())), c);

        c.gridx++;
        c.insets = new Insets(0, 0, 0, 2);
        infoPanel.add(new JLabel("Score record:"), c);

        c.gridx++;
        c.insets = new Insets(0, 0, 0, 0);
        infoPanel.add(new JLabel(Integer.toString(stage.getScoreRecord())), c);
    }

    /**
     * @return The play button.
     */
    public Object getPlayButton()
    {
        return playButton;
    }
}
